package middleware

import (
	"context"
	"ruoyi-go-echo-ddd/internal/infrastructure/persistence/config"
	"ruoyi-go-echo-ddd/internal/infrastructure/utils"

	"github.com/google/uuid"
	"github.com/labstack/echo/v4"
	"github.com/rs/zerolog"
)

// 定义上下文键类型
type contextKey string

// 定义具体的键常量
const (
	requestIDKey contextKey = "request_id"
	loggerKey    contextKey = "logger"
)

// GetRequestID 获取请求ID
func GetRequestID(ctx context.Context) string {
	if id, ok := ctx.Value(requestIDKey).(string); ok {
		return id
	}
	return ""
}

// SetRequestID 设置请求ID到上下文
func SetRequestID(ctx context.Context, id string) context.Context {
	return context.WithValue(ctx, requestIDKey, id)
}

// GetLogger 获取日志器
func GetLogger(c echo.Context) zerolog.Logger {
	if l, ok := c.Request().Context().Value(loggerKey).(zerolog.Logger); ok {
		return l
	}
	// 回退到全局日志器
	return config.ZeroLog
}

// RequestIdLoggerMiddleware 请求ID中间件
func RequestIdLoggerMiddleware() echo.MiddlewareFunc {
	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			// 从请求头获取或生成请求ID
			reqID := c.Response().Header().Get(echo.HeaderXRequestID)
			if reqID == "" {
				reqID = generateRequestID()
				c.Response().Header().Set(echo.HeaderXRequestID, reqID)
			}

			// 创建带有请求ID的zerolog的子日志器
			logger := zerolog.DefaultContextLogger.With().Str("request_id", reqID).Logger()

			config.ZeroLog = logger

			// 将子日志器设置为当前请求的默认上下文日志器
			ctx := logger.WithContext(c.Request().Context())

			// 更新请求上下文
			c.SetRequest(c.Request().WithContext(utils.SetValForContext(ctx, "request_id", reqID)))

			return next(c)
		}
	}
}

// 生成请求ID
func generateRequestID() string {
	// 使用更高效的UUID生成库
	return uuid.New().String()
}
